%% coding: latin-1
%%这是注释
%%Erlang语言的基本学习内容涵盖其中

-module(test).    %模块声明，一般和文件名相同
%-export([add/2]). %对外函数声明，在其他模块中可以使用这个函数
-compile(export_all).
-record(person,{name,age,phone}). %记录声明，一个标记，三个域，在Shell中要有rr（文件名）读入似乎。
-define(author,"gerry xiao"). %宏定义，使用时前面加上？号

hello() ->
    io:format("hello world ~n"). %io是模块名，调用模块函数使用模块：函数形式

print_contact(#person{name=Name,age=Age,phone=Phone})
    when Phone =/= undefined ->
    io:format("Contact: ~s is ~p years old,and phone is  ~s ~n",[Name,Age,Phone]). %模式匹配，功能强大


sum(L) ->                 %同名不同参数的函数在erlang中是完全不同的函数
    sum(L,0).

%sum([],N) ->
%    N;                     %同参数的同名函数不同子句。
%sum([H|T],N) ->
%    sum(T,H+N).

math_func(X,Y) ->
    math:sqrt(X*X + Y*Y).

fac(0) ->
    1;
fac(N) ->
    N*fac(N-1).

tail_fac(N) ->
    tail_fac2(N,1).
tail_fac2(0,N) ->
    N;
tail_fac2(M,N) ->
   tail_fac2(M-1,N*M).

area({rectangle,Width,Ht})->
    Width*Ht;
area({circle,R}) ->
    3.14159*R*R.

loop()->
    receive
       	{From,{rectangle,W,H}} ->
	    io:format("Area of rectangle is ~p~n",[W*H]),
	    From ! W*H,
	    loop();
	{From,{circle,R}} ->
	    io:format("Area of circle is ~p~n",[3.1415926*R*R]),
	    From ! 3.1415926*R*R,
	    loop();
        {From,Other}  ->
	    io:format("I don't know the area of a ~p ~n",[Other]),
	    From ! {error,Other},
	    loop()
    end.

rpc(Pid,Request) ->
    Pid ! {self(),Request},
    receive 
	Response -> Response
    end.
    

on_exit(Pid,Fun)->
    spawn(fun() ->
		  process_flag(trap_exit,true),
		  link(Pid),
		  receive
		      {'EXIT',Pid,Why} ->
			  Fun(Why)
		  end
            end).

nano_get_url() ->
    nano_get_url("www.baidu.com").
nano_get_url(Host) ->
    {ok,Socket}=gen_tcp:connect(Host,80,[binary,{packet,0}]),
    ok=gen_tcp:send(Socket,"GET / HTTP/1.0\r\n\r\n"),
    receive_data(Socket,[]).

receive_data(Socket,SoFar) ->
    receive
	{tcp,Socket,Bin} ->
	    receive_data(Socket,[Bin|SoFar]);
	{tcp_closed,Socket} ->
	    list_to_binary(lists:reverse(SoFar))
    end.


test_c_function_call() ->  %%c function in comm.c and driver.c under same dir.
    spawn(fun() ->
		  register(test,self()),
		  process_flag(trap_exit,true),
		  Port=open_port({spawn, "./a.exe"},[{packet,2}]), %a.exe is gcc comm.c driver.c
		  loop(Port)
	   end).
stop() ->
    test ! stop.

twice(X) ->
    call_port({twice,X}).
sum(X,Y)->
    call_port({sum,X,Y}).

call_port(Msg) ->
    test ! {call,self(),Msg},
    receive
	{test,Result} ->
	    Result
    end.

loop(Port) ->
    receive
	{call,Caller,Msg} ->
	    Port ! {self(),{command,encode(Msg)}},
	    receive
		{Port,{data,Data}}->
		    Caller ! {test,decode(Data)}
	    end,
	    loop(Port);
	stop ->
	    Port ! {self(),close},
	    receive
		{Port,closed} ->
		    exit(normal)
	    end;
	{'EXIT',Port,Reason} ->
	    exit({port_terminated,Reason})
    end.

encode({twice,X}) ->
	      [1,X];
encode({sum,X,Y}) -> [2,X,Y].

decode([Int]) ->
    Int.
